//分片上传下载 - 实验
//目前只实验,具体设计会在其他目录出现

#[path = "./File交互控制器.rs"]
pub mod File交互控制器;

use std::fs::{DirBuilder, File};
use std::io;
use std::io::{Read, Write};

pub static 分片_root_path: &'static str ="./public/分片/";

trait 分片 {
	
	/**
		#推入一个分片
	*/
	fn push_data<const U:usize>(&mut self,data:[u8;U]);
	/**
		#文件是否完整
		**return** : [`ture`]:完整 , [`false`]:不完整
	 */
	fn is_complete(&self) ->bool;
	/**
		#合成文件
		**return** : 若[`分片::is_complete`]返回[`false`],则返回[`None`]
	*/
	fn make_file(&self)->Option<File>;
	/**
		#删除所有分片
	 */
	fn delete_all_piece(&mut self);
}



/**
	[`分片_root_path`] 下建立以**md5**命名的目录

    在此目录下的文件名,就是0..**all_piece** , 也就是 0,1,2,3,...

    最后合成是名字是 "-1"
*/
struct FileData {
	///文件名
	name: String,
	///文件大小
	length: usize,
	///总片数
	all_piece: usize,
	///当期片数
	now_piece: usize,
	///md5 充当 id,并且在 [`分片_root_path`] 下建立的目录名,就是md5
	md5:String,
}

impl FileData {
	pub fn new(name: String, length: usize,all_piece:usize,md5:String)->FileData{
		FileData::new_dir(&md5);
		FileData{
			name,
			length,
			all_piece,
			md5,
			now_piece:0
		}
	}
	fn new_dir(md5:&String) {
		if let Err(e) = DirBuilder::new().create( 分片_root_path.to_string() + md5) {
			//目录重复,也就是md5重复,说明是 续传
			todo!()
		}
	}
	fn self_dir(&self) -> String {
		format!("{}{}/",分片_root_path,&self.md5)
	}
}

impl 分片 for FileData {
	fn push_data<const U: usize>(&mut self, data: [u8; U]) {
		let mut file =
			File::create(format!("{}{}",self.self_dir(),self.now_piece)).unwrap();
		file.write(&data);
		
		self.now_piece += 1;
	}
	
	fn is_complete(&self) -> bool {
		self.now_piece == self.all_piece
	}
	
	fn make_file(&self) -> Option<File> {
		if !self.is_complete() { return None; }
		let mut file = File::create(self.self_dir() + "-1" ).unwrap();
		for v in 0..self.all_piece {
			let file_name = v.to_string();
			let mut f = File::open(file_name).unwrap();
			let mut buf = [0_u8;128];
			while let Ok(v) = f.read(&mut buf)  {
				if v==0 { break; }
				file.write(&buf[0..v]);
			}
		}
		Some(file)
	}
	
	fn delete_all_piece(&mut self) {
		todo!()
	}
}